#pragma once
#include "Enginehead.h"
#include "ResourceBase.h"
#include "Device.h"
#include "GPUBuffer.h"
namespace mini
{
	enum VSConstBuffLabel
	{
		WVPMATRIX_Index		  = 0,
		DiffuseColor_Index    = 1,
		AmbientColor_Index    = 2,
		SpecularColor_Index   = 3,
	};

	class CShader : public CResourceBase
	{
		friend class CMaterial;
		friend class CShaderUnit;
		friend class CMaterialUnit;

	public:
		CShader();
		virtual ~CShader();
		void setDevice(CDevice* pDevice);
		bool createVextexShader(const std::string& fileName, const std::string& strMain, const std::string& strVersion);
		bool createVextexShader(const std::string& fileName, const std::string& strMain, const std::string& strVersion, std::vector<D3D11_INPUT_ELEMENT_DESC> pInputElement);
		bool createHullShader(const std::string& fileName, const std::string& strMain, const std::string& strVersion);
		bool createDomainShader(const std::string& fileName, const std::string& strMain, const std::string& strVersion);
		bool createPixelShader(const std::string& fileName, const std::string& strMain, const std::string& strVersion);
		bool createGeometryShader(const std::string& fileName, const std::string& strMain, const std::string& strVersion);

		void commitToGpu(DeviceContext* pDeviceContext);
		bool addPSParam( const std::string& name, INT32 size, INT32 nRegister, INT32 nOffset);
		bool addDSParam( const std::string& name, INT32 size, INT32 nRegister, INT32 nOffset);
		bool addHSParam(const std::string& name, INT32 size, INT32 nRegister, INT32 nOffset);
		bool addVSParam(const std::string& name, INT32 size, INT32 nRegister, INT32 nOffset);
		bool addGSParam(const std::string& name, INT32 size, INT32 nRegister, INT32 nOffset);
		bool addTextureConstBufferParam(const std::string& name, INT32 size, INT32 nRegister, INT32 nOffset);
		bool addStructedBuffer(const std::string& name, INT32 structSize, INT32 size, INT32 nRegister, INT32 nOffset);
		bool addTextureParam(const std::string& name, INT32 size, INT32 nRegister, INT32 nOffset);
		bool addTypeBufferParam(const std::string& name, INT32 size, INT32 nRegister, INT32 nOffset);

		bool updateVSConstBuffer(int nRegistIndex, void* pData, int offset);
		bool updateTextureConstBuffer(int nRegistIndex, void* pData, int offset);
		bool updateTextureBuffer(int nRegistIndex, void* pData, int offset);
		bool updateTypeBuffer(int nRegistIndex, void* pData, int offset);
		bool updateStructedBuffer(int nRegistIndex, void* pData, int offset);
		bool updateHSConstBuffer(const std::string& name, void* pData, int offset);
		bool updateDSConstBuffer(const std::string& name, void* pData, int offset);
		bool updatePSConstBuffer(const std::string& name, void* pData, int offset);
		bool updateGSConstBuffer(const std::string& name, void* pData, int offset);
		void use(DeviceContext* pDeviceContext, int nLayoutIndex);
		void setTopology(UINT32 topology);
		UINT32 getTopology() const;

		//bool updateWVPMatrixBuffer(DeviceContext* pContext, void* pData, UINT32 uStartSlot = 0);

	private:
		void applyConstBuffer(DeviceContext* pContext);

	private:
		UINT32	mPixelConstBufferStride = 0;
		UINT32	mDomainConstBufferStride = 0;
		UINT32	mHullConstBufferStride = 0;
		UINT32	mVertexConstBufferStride = 0;
		UINT32	mGeometryConstBufferStride = 0;
		UINT32	mTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
		CDevice*						mpDevice;
		std::string						mVertexShaderName;
		std::string						mHullShaderName;
		std::string						mDomainShaderName;
		std::string						mPixelShaderName;
		std::string						mGeometryShaderName;

#ifdef WIN32
		ID3D11VertexShader*	m_vertexShader = nullptr;
		ID3D11HullShader*	m_HullShader = nullptr;
		ID3D11DomainShader* m_DomainShader = nullptr;
		ID3D11PixelShader*  m_pixelShader = nullptr;
		ID3D11GeometryShader* m_pGeometryShader = nullptr;

		std::vector<ID3D11InputLayout*>	mLayoutList;
	//	CGPUBuffer*			mPixelConstBuffer = nullptr;
	//	std::list<CGPUBuffer*>
		std::map<UINT32, std::tuple<UINT32, CGPUBuffer*, void*, int>>	mVertexConstBufferMap;
		std::map<UINT32, std::tuple<UINT32, CGPUBuffer*, void*, int>>	mTextureConstBufferMap;
		std::map<UINT32, std::tuple<UINT32, ID3D11Texture1D*, void*, int>>	mTextureBufferMap;
		std::map<UINT32, std::tuple<UINT32, CGPUBuffer*, void*, int>>	mTypeBufferMap;
		std::map<UINT32, std::tuple<UINT32, CGPUBuffer*, void*, int>>	mStructBufferMap;

		std::map<std::string, std::tuple<UINT32, UINT32, CGPUBuffer*, void*, int>>mHullParamMap;
		std::map<std::string, std::tuple<UINT32, UINT32, CGPUBuffer*, void*, int>>mDomainParamMap;
		std::map<std::string, std::tuple<UINT32, UINT32, CGPUBuffer*, void*, int>>mPixelParamMap;
		std::map<std::string, std::tuple<UINT32, UINT32, CGPUBuffer*, void*, int>>mGeometryParamMap;

		std::map<UINT32, ID3D11ShaderResourceView*>				mTextureBufferResourceViewMap;
		std::map<UINT32, ID3D11ShaderResourceView*>				mTextureConstResourceViewMap;
		std::map<UINT32, ID3D11ShaderResourceView*>				mTypeResourceViewMap;
		std::map<UINT32, ID3D11ShaderResourceView*>				mStructedResourceViewMap;
#else

#endif
	};
}